/**
* @file
* @brief This file handles all storage/database related functions.
*/

//-------------------------------------------------------
// Header Files
//-------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "storage.h"
#include "utils.h"
#include "server.h" // for client connection information
	FILE* hahaFile;//for counting abort
//-------------------------------------------------------
// Constants
//-------------------------------------------------------

// @note This method below only works till M3 and doesn't work for M4
// Global variable to keep track of single client's connection and authentication
bool authen = false;///< Global variable to keep track of single client's connection and authentication 
bool connected = false;///< Global variable to keep track of single client's connection and authentication
// @note Client cannot exit by ctrl+c as it is compiled together with storage.c

//-------------------------------------------------------
// Storage Functions
//-------------------------------------------------------
/**
* This function connects to a port with hostname
* @param hostname localhost
* @param port A port number
* @return NULL if unsuccessful
*/
// @note: Always use {"localhost", 1376)
void* storage_connect(const char *hostname, const int port)
{
    // Check parameters
    // 1. Check if NULL
    if((hostname == NULL))
    {
	errno = ERR_INVALID_PARAM;
	//perror("Error: hostname or port is NULL in storage_connect()\n");
	return NULL;
    }
    // 2. Check if it is too long
    if (strlen(hostname) > MAX_HOST_LEN)
    {
        errno = ERR_INVALID_PARAM;
        sprintf(message, "Error: hostname %s exceeds maximum length of %d\n", hostname, MAX_HOST_LEN);
	printf("%s", message);
        logger(fileClient, message);
        return NULL;
   }
    // Get number of digits of port
    int count = numDigits(port); // defined in utils.h
    if (count > MAX_PORT_LEN)
    {
        errno = ERR_INVALID_PARAM;
        sprintf(message, "Error: port %d exceeds maximum length of %d\n", port, MAX_PORT_LEN);
        printf("%s", message);
        logger(fileClient, message);
        return NULL;
    }
    // 3. Check if satisfy constraint
    // 3.1 Check if hostname satisfy constraint ( localhost or d.d.d.d) , where d is between 0 to 255
    // Truncate hostname to remove spaces,
    char text[MAX_HOST_LEN+1], truncHostName[MAX_HOST_LEN+1];
    strcpy(text, hostname); // create a copy of hostname
    int c1 = 0, c2 = 0;
    // Truncate all trailing spaces
    while (text[c1] != '\0')
    {
	if (!(text[c1] == ' '))
	{
	    truncHostName[c2] = text[c1];
        c2++;
      }
      c1++;
    }
    truncHostName[c2] = '\0';
    if (strcmp(truncHostName,"localhost") != 0) // TODO: check if it works with "localhost   " in input
    {
	// Check if IP address satisfy constraint
	//inet_pton() returns 1 on success.
	//It returns -1 if there was an error (errno is set), or 0 if the input isn't a valid IP address.
	struct sockaddr_in saTemp;
	// store this IP address in sa:
	int IPCheck = inet_pton(AF_INET, truncHostName, &(saTemp.sin_addr)); // for IPv4
		// returns 1 on success, -1 if there was an error, 0 if input isn't valid
	if (IPCheck == 0)
	{
	    errno = ERR_INVALID_PARAM;
	    sprintf(message, "Error: %s is not a valid IP Address\n", truncHostName);
	    printf("%s", message);
	    logger(fileClient, message);
	    return NULL;
	}
    }
    // else (hostname == localhost) which is valid
    // 3.2 Check if port satisfy constraint (d), 0 <= d <= 65535
    if( (port > 65535) || (port < 0))
    {
	errno = ERR_INVALID_PARAM;
	sprintf(message, "Error: %d is not a valid port number\n", port);
	printf("%s", message);
	logger(fileClient, message);
	return NULL;
    }
    // Create a socket.
    // @note: Both server and clients must create socket before it can connect to it
    int sockfd = socket(PF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
	errno = ERR_CONNECTION_FAIL;
	return NULL;
    }
    // Get info about the server.
    struct addrinfo serveraddr, *res;
    // Initialize
    memset(&serveraddr, 0, sizeof serveraddr);
    serveraddr.ai_family = AF_UNSPEC; // Ipv4 or IPv6
    serveraddr.ai_socktype = SOCK_STREAM;
    char portstr[MAX_PORT_LEN];
    // write onto portstr MAX_PORT_LEN for the value port given
    // Basically converts the int port value given into a string
    snprintf(portstr, sizeof portstr, "%d", port);
		//e.g. n = (buffer, 10, "haha what %d you %d, 2, 3)
    // Gets address info of "localhost", "1376", hint of type of address structure, list of socket address structures found)
    int status = getaddrinfo(truncHostName, portstr, &serveraddr, &res); // returns 0 if succeeds, or one of error codes if fails
    if (status != 0)
    {
	errno = ERR_CONNECTION_FAIL;
	return NULL;
    }
    // Connect to socket referred by sockfd and address referred to be res->ai_addr which has size res->ai_addrlen
    status = connect(sockfd, res->ai_addr, res->ai_addrlen); // returns 0 if successful and -1 if fails
    if (status != 0)
    {
	errno = ERR_CONNECTION_FAIL;
	return NULL;
    }
    // JUSTIFY 1: A logger call here to know connection is successful to right port, we know it is successful here
    //		  cause getaddrinfo and connect both returns a 1 to status
    // Store connected information into client linked list in server.c when it accepts a new client (in server.c)
    printf("Connection in storage.c is successful with port %s\n", portstr);
    sprintf(message, "Connection in storage.c is successful with port %s\n", portstr);
    logger(fileClient, message);
    connected = true; // let global variable be true
    // Return a pointer to the socket file descriptor
    return (void*) sockfd;
}

/**
* This function autheticates a connection to socket
* and prints to socketfd what has been authenticated
* @return 0 if successful, otherwise, returns -1
*/
int storage_auth(const char *username, const char *passwd, void *conn)
{
    // Check parameters
    // 1. Check if NULL
    if((username == NULL) || (passwd == NULL) || (conn == NULL) )
    {
        errno = ERR_INVALID_PARAM;
        printf("Error: username or password or connection descriptor is NULL in storage_auth()\n");
        return -1;
    }
    if (strlen(username) > MAX_USERNAME_LEN)
    {
        errno = ERR_INVALID_PARAM;
        sprintf(message, "Error: username %s exceeds maximum length of %d\n", username, MAX_USERNAME_LEN);
        printf("%s", message);
        logger(fileClient, message);
        return -1;
   }
    if (strlen(passwd) > MAX_ENC_PASSWORD_LEN) // assume max_enc is same as max_passwd
    {
        errno = ERR_INVALID_PARAM;
        sprintf(message, "Error: passwd %s exceeds maximum length of %d\n", passwd, MAX_ENC_PASSWORD_LEN);
        printf("%s", message);
        logger(fileClient, message);
        return -1;
   }
    // Connection is really just a socket file descriptor.
    int sockfd = (int)conn;
    int n = 0;
    int errcode = 0;

    // Check if connected
/*if(getclient(sockfd) == NULL) */ // This doesn't work, don't use this approach
    if (connected == false)
    {
	errno = ERR_CONNECTION_FAIL;
        sprintf(message, "Error: Client fd:%d not connected in storage_auth() \n", sockfd);
        printf("%s", message);
        logger(fileClient, message);
	return -1;
    }
    // Check if authenticated
    // Send some data.
    // Create buffer
    char buf[MAX_CMD_LEN];
    memset(buf, 0, sizeof buf);
    // Generate encrypted password
    char *encrypted_passwd = generate_encrypted_password(passwd, NULL);
    char text[MAX_HOST_LEN+1], truncUserName[MAX_HOST_LEN+1];
    strcpy(text, username); // create a copy of username
    int c1 = 0, c2 = 0;
    // Truncate all trailing spaces for username as that is allowed in any login information site
    while (text[c1] != '\0')
    {
        if (!(text[c1] == ' '))
        {
            truncUserName[c2] = text[c1];
        c2++;
      }
      c1++;
    }
    truncUserName[c2] = '\0';
    // Write to buffer "Authenticated username and encrypted password"
    snprintf(buf, sizeof buf, "AUTH@%s@%s\n", truncUserName, encrypted_passwd);
    // Send buffers till done, then receives to buffer till done
    if (sendall(sockfd, buf, strlen(buf)) == 0 && recvline(sockfd, buf, sizeof buf) == 0)
    {
	// @note: sendall() makes sure it sends all strlen(buf) before it finishes
		// else, it will return -1 and wont go to recvline
	// Return 0 if successful for both send buffer to sockfd and recv from sockfd to buffer
    	// JUSTIFY 2: A logger call here to know if the data and sends have been sent & received properly
/*printf("Buffer received is %s\n", buf);*/
// PROTOCOL:
// 1 => success
// 0 => failure

	int success = atoi(buf);
	if(success == 1)
	{
	    sprintf(message, "Both sendall and receive all in storage_auth successful\n");
	    logger(fileClient, message);
	    authen = true; // set global authen
	    return 0;
	}
    }
    // else
    errno = ERR_AUTHENTICATION_FAILED;
    authen = false;
    return -1;
}

/**
* This function is used to get a record given a key and table
* It populates the record structure with info if found, otherwise,
* record is not modified
* @param table containing key of interest
* @param key's value to be get
* @param record structure to store information of value gotten
* @return returns 0 if successful, otherwise returns -1
*/
int storage_get(const char *table, const char *key, struct storage_record *record, void *conn)
{
    // Check parameters
    // 1. Check if NULL @note record cannot be NULL
    if((table == NULL) || (key == NULL) || (record == NULL) || (conn == NULL))
    {
        printf("Error: table or key or record or conn file descriptor is NULL in storage_get()\n");
	errno = ERR_INVALID_PARAM;
        return -1;
    }

    // 2. Check if too long
    if (strlen(table) > MAX_TABLE_LEN)
    {
        sprintf(message, "Error: table %s exceeds maximum length of %d in storage_get() \n", table, MAX_TABLE_LEN);
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_INVALID_PARAM;
        return -1;
    }
    if (strlen(key) > MAX_KEY_LEN)
    {
        sprintf(message, "Error: key %s exceeds maximum length of %d in storage_get() \n", key, MAX_KEY_LEN);
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_INVALID_PARAM;
        return -1;
    }

    // Connection is really just a socket file descriptor.
    int sockfd = (int)conn;
    int n = 0;
    int errcode = 0;
    // Send some data.
    // 3. Check if satisfy constraint for table, key
    if(!checkName(table))
    {
        sprintf(message, "table does not satisfy constraint in storage_get() \n");
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_INVALID_PARAM;
	return -1;
    }
    if(!checkName(key))
    {
        sprintf(message, "key does not satisfy constraint in storage_get() \n");
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_INVALID_PARAM;
	return -1;
    }
    // Check if connected
    if(connected == false)
    {
        sprintf(message, "Error: Client fd:%d not connected in storage_get() \n", sockfd);
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_CONNECTION_FAIL;
        return -1;
    }
    // Check if authenticated
    if (authen == false)
    {
        sprintf(message, "Error: Client fd:%d not authenticated yet in storage_get() \n", sockfd);
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_NOT_AUTHENTICATED;
        return -1;
    }
    char buf[MAX_CMD_LEN+1];
    memset(buf, 0, sizeof buf);
    snprintf(buf, sizeof buf, "GET@%s@%s\n", table, key);
    if (sendall(sockfd, buf, strlen(buf)) == 0 && recvline(sockfd, buf, sizeof buf) == 0)
    {
// PROTOCOL:
// 1 VALUE=> value given
// -1 => key not found
// -2 => table not found

    char* args[4];
    // Get arguments into args and numArgs holds number of arguments given whic is 3 or 4.
    // @note: Need to free all args once done
    int numArgs = getArguments(args, buf);
printf("Argument 1 is:\n%s\n whereas argument 2 is:\n%s\n", args[0], args[1]);
        int success = atoi(args[0]);
	switch (success)
	{
	// Check if table is found
	    case -2:
            	sprintf(message, "Error: Table not found in storage_set() \n");
		printf("%s", message);
            	logger(fileClient, message);
		errno = ERR_TABLE_NOT_FOUND;
		return -1;
        	break;
    	    case -1:
	// Check if key is found
                sprintf(message, "Error: Key not found in storage_set() \n");
                printf("%s", message);
                logger(fileClient, message);
				numArgs = -1;
		record->metadata[0] = (uintptr_t) numArgs;	//	Set record to 0
		errno = ERR_KEY_NOT_FOUND;
		return -1;
		break;
    	    case 0:
	// Check if key is found
                sprintf(message, "Error: Key not found in storage_set() \n");
                printf("%s", message);
                logger(fileClient, message);
				numArgs = -1;
		record->metadata[0] = (uintptr_t) numArgs;	//	Set record to 0
		errno = ERR_KEY_NOT_FOUND;
		return -1;
		break;
    	    case 1:
                sprintf(message, "Success: Key value pair gotten from storage_set() \n");
                printf("%s", message);
                logger(fileClient, message);
		// Note: Copies buffer to record->value
    		strncpy(record->value, args[1], sizeof record->value);
		numArgs = atoi(args[2]);
		record->metadata[0] = (uintptr_t) numArgs;
    		// JUSTIFY 3: A logger call here to know that buffer has been copied to record value successfully
    		sprintf(message, "Copied buffer to record value is:\n%s\n", record->value);
    		logger(fileClient, message);
		return 0;
        	break;
	    default: // should never come here
		break;
	}
	return 0;
    }
    return -1;
}

/**
* This function sets a record given a key and table
* If key exist, record is update,
* If key exist, but record is NULL, the key valued pair are deleted from table
* If key does not exist, will set errno = ERR_KEY_NOT_FOUND
* If table does not exist, will set errno = ERR_TABLE_NOT_FOUND
* @param table which contains key
* @param key to be set
* @param record structure which contains the record to be set of key, may be NULL for deletion
* @return 0 if successful, otherwise returns -1
*/
int storage_set(const char *table, const char *key, struct storage_record *record, void *conn)
{
    // Check parameters
    // 1. Check if NULL @note record can be NULL
    if((table == NULL) || (key == NULL) || (conn == NULL) || (table == '\0') || (key == '\0'))
    {
        printf("Error: table or key or conn file descriptor is NULL in storage_set()\n");
	errno = ERR_INVALID_PARAM;
        return -1;
    }
    // 2. Check if too long for table, key, record
    if (strlen(table) > MAX_TABLE_LEN)
    {
        sprintf(message, "Error: table %s exceeds maximum length of %d in storage_set() \n", table, MAX_TABLE_LEN);
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_INVALID_PARAM;
        return -1;
    }
    if (strlen(key) > MAX_KEY_LEN)
    {
        sprintf(message, "Error: key %s exceeds maximum length of %d in storage_set() \n", key, MAX_KEY_LEN);
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_INVALID_PARAM;
        return -1;
    }
    if (record != NULL)
    {
   	if (strlen(record->value) > MAX_VALUE_LEN)
    	{
            sprintf(message, "Error: record's value %s exceeds maximum length of %d in storage_set() \n",record->value, MAX_VALUE_LEN);
            printf("%s", message);
            logger(fileClient, message);
	    errno = ERR_INVALID_PARAM;
            return -1;
	}
    }

    // Connection is a socket file descriptor.
    int sockfd = (int)conn;
    // Initialize buffer
    char buf[MAX_CMD_LEN+1];
    int n = 0;
    int errcode = 0;
    // 3. Check if satisfy constraint for table, key, record
    if(!checkName(table))
    {
        sprintf(message, "table does not satisfy constraint in storage_set() \n");
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_INVALID_PARAM;
        return -1;
    }
    if(!checkName(key))
    {
        sprintf(message, "key does not satisfy constraint in storage_set() \n");
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_INVALID_PARAM;
        return -1;
    }
    if (record != NULL)
    {
        if(!checkValue(record->value))
        {
	    sprintf(message, "record's value does not satisfy constraint in storage_set() \n");
            printf("%s", message);
            logger(fileClient, message);
	    errno = ERR_INVALID_PARAM;
            return -1;
	}
    }

    // Check if connected
    if (connected == false)
    {
        sprintf(message, "Error: Client fd:%d not connected in storage_set() \n", sockfd);
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_CONNECTION_FAIL;
        return -1;
    }
    // Check if authenticated
    if (authen == false)
    {
        sprintf(message, "Error: Client fd:%d not authenticated yet in storage_set() \n", sockfd);
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_NOT_AUTHENTICATED;
        return -1;
    }
    memset(buf, 0, sizeof buf);
    if(record == NULL)
    {
		int temp = 0;
    	snprintf(buf, sizeof buf, "SET@%s@%s@NULL@%d\n", table, key, temp);
    }
    // Copy str to buffer indicating has been set
    else
    {
	int temp = 0;
	temp = (int) record->metadata[0];
	snprintf(buf, sizeof buf, "SET@%s@%s@%s@%d\n", table, key, record->value, temp);
    }

    // send buffer to sockfd and receive anything from sockfd
// PROTOCOL:
// 3 => deleted value
// 2 => updated value
// 1 => inserted value
// -1 => key not found
// -2 => table not found
    if (sendall(sockfd, buf, strlen(buf)) == 0 && recvline(sockfd, buf, sizeof buf) == 0) // ERROR OCCURS HERE
    {
        int success = atoi(buf);
	switch (success)
	{
	// Check if transaction aborted
	    case -5:
			sprintf(message, "Error: Transaction aborted \n");
			printf("%s", message);
			logger(fileClient, message);
			errno = ERR_TRANSACTION_ABORT;
// hahaFile defined above 
hahaFile = fopen("TransactionAbort.txt", "a+");
fputs ("ABORTHAHA\n",hahaFile);
fclose (hahaFile);
			return -1;
	// Check if invalid params in values
	    case -3:
			sprintf(message, "Error: Invalid Parameters \n");
			printf("%s", message);
			logger(fileClient, message);
			errno = ERR_INVALID_PARAM;
			return -1;

	// Check if table is found
	    case -2:
            	sprintf(message, "Error: Table not found in storage_set() \n");
		printf("%s", message);
            	logger(fileClient, message);
		errno = ERR_TABLE_NOT_FOUND;
		return -1;
        	break;
    	    case -1:
	// Check if key is found
                sprintf(message, "Error: Key not found in storage_set() \n");
                printf("%s", message);
                logger(fileClient, message);
		errno = ERR_KEY_NOT_FOUND;
		return -1;
		break;
    	    case 1:
                sprintf(message, "Success: Key value pair inserted in storage_set() \n");
                printf("%s", message);
                logger(fileClient, message);
		return 0;
        	break;
	    case 2:
                sprintf(message, "Success: Key value pair updated in storage_set() \n");
                printf("%s", message);
                logger(fileClient, message);
		return 0;
		break;
	    case 3:
                sprintf(message, "Success: Key value pair deleted in storage_set() \n");
                printf("%s", message);
                logger(fileClient, message);
		return 0;
		break;
	    default: // should never come here
		break;
	}
	return 0;
    }
    return -1;
}

/**
* This function disconnects a given sockfd
* @param conn The sockfd to be disconnected
* @return returns 0 if successful, otherwise, returns -1
*/
int storage_disconnect(void *conn)
{
    // Check parameter
    if (conn == NULL)
    {
        printf("Error: conn file descriptor is NULL in storage_disconnect()\n");
	errno = ERR_INVALID_PARAM;
        return -1;
    }
    // Cleanup
    int sockfd = (int)conn;
    if(close(sockfd) != 0)
    {
	printf("Error: Disconnect Unsuccessful\n");
	errno = ERR_UNKNOWN;
	return -1;
    }
    // JUSTIFY 4: A logger call here to know disconnect is successful
    printf("Disconnection in storage.c is successful\n");
    sprintf(message, "Disconnection in storage.c is successful\n");
    logger(fileClient, message);
    connected = false; // connected global variable is false
    authen = false; // user must authenticate again
    return 0;
}

/**
 * @brief Query the table for records, and retrieve the matching keys.
 *
 * @param table A table in the database.
 * @param predicates A comma separated list of predicates.
 * @param keys An array of strings where the keys whose records match the 
 * specified predicates will be copied.  The array must have room for at 
 * least max_keys elements.  The caller must allocate memory for this array.
 * @param max_keys The size of the keys array.
 * @param conn A connection to the server.
 * @return Return the number of matching keys (which may be more than
 * max_keys) if successful, and -1 otherwise.
 *
 * On error, errno will be set to one of the following, as appropriate: 
 * ERR_INVALID_PARAM, ERR_CONNECTION_FAIL, ERR_TABLE_NOT_FOUND, 
 * ERR_KEY_NOT_FOUND, ERR_NOT_AUTHENTICATED, or ERR_UNKNOWN.
 *
 * Each predicate consists of a column name, an operator, and a value, each
 * separated by optional whitespace. The operator may be a "=" for string
 * types, or one of "<, >, =" for int and float types. An example of query
 * predicates is "name = bob, mark > 90".
 */
int storage_query(const char *table, const char *predicates, char **keys, 
	const int max_keys, void *conn)
{
	int tempError = 0;
	int i = 0;
	int j = 0;
	int k = 0;

    // Check parameters
    // 1. Check if NULL @note record can be NULL
    if((table == NULL) || (conn == NULL) || (table == '\0'))
    {
        printf("Error: table or conn file descriptor is NULL\n");
	errno = ERR_INVALID_PARAM;
        return -1;
    }
    // 2. Check if too long for table, key, record
    if (strlen(table) > MAX_TABLE_LEN)
    {
        sprintf(message, "Error: table %s exceeds maximum length of %d\n", table, MAX_TABLE_LEN);
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_INVALID_PARAM;
        return -1;
    }
    // Connection is a socket file descriptor.
    int sockfd = (int)conn;
    // Initialize buffer
    char buf[MAX_CMD_LEN+1];
    int n = 0;
    int errcode = 0;
    // 3. Check if satisfy constraint for table, key, record
    if(!checkName(table))
    {
        sprintf(message, "table does not satisfy constraint\n");
        printf("%s", message);
        logger(fileClient, message);
	errno = ERR_INVALID_PARAM;
        return -1;
    }

    // Check if connected
    if (connected == false)
    {
        sprintf(message, "Error: Client fd:%d not connected\n", sockfd);
        printf("%s", message);
        logger(fileClient, message);
		tempError = ERR_CONNECTION_FAIL;
    }
    // Check if authenticated
    if (authen == false)
    {
        sprintf(message, "Error: Client fd:%d not authenticated yet\n", sockfd);
        printf("%s", message);
        logger(fileClient, message);
		if(tempError==0);
			tempError=ERR_NOT_AUTHENTICATED;
        return -1;
    }
    memset(buf, 0, sizeof buf);
    // Copy str to buffer indicating has been set
    if((predicates!=NULL)&&(predicates!='\0'))
    	snprintf(buf, sizeof buf, "QUE@%s@%s@%d\n", table, predicates, max_keys);
    else
	snprintf(buf, sizeof buf, "QUE@%s@NULL@%d\n", table, max_keys);
    // send buffer to sockfd and receive anything from sockfd
// PROTOCOL:
// 3 => deleted value
// 2 => updated value
// 1 => inserted value
// -1 => key not found
// -2 => table not found
    if (sendall(sockfd, buf, strlen(buf)) == 0 && recvline(sockfd, buf, sizeof buf) == 0)
    {
        int success = atoi(buf);
	if(success==0)
		success=tempError;
	switch (success)
	{
	// Check if invalid params in values
		case -3:
			sprintf(message, "Error: Invalid Parameters \n");
			printf("%s", message);
			logger(fileClient, message);
			errno = ERR_INVALID_PARAM;
			return -1;
			break;
		case -2:
			sprintf(message, "Error: Missing Table \n");
			printf("%s", message);
			logger(fileClient, message);
			errno = ERR_TABLE_NOT_FOUND;
			return -1;
			break;
	    default: // should never come here
		        sprintf(message, "Success: Query succeeded %s\n", buf);
                printf("%s\n", message);
                logger(fileClient, message);
				i = 1; //	Start at second element to get rid of '1'
				j = 0;
				k = 0;
				while(buf[i]!='\0')	//	Read all into keys.
				{
					if(buf[i]=='@')
						i++;
					k = 0;
					while(buf[i]!='@'&&buf[i]!='\0')
					{
						keys[j][k]=buf[i];
						i++; k++;
					}
					keys[j][k]='\0';
					j++;
				}
			return success;
		break;
	}
	return 0;
    }
    return -1;
}
		
